<template>
    <div class="gomoku-container">
        <div class="game-info">
            <van-tag type="primary">当前回合: {{ currentPlayer === 'human' ? '你的回合' : 'AI思考中...' }}</van-tag>
            <van-tag :type="winner ? 'danger' : 'success'">
                {{ winner ? (winner === 'human' ? '你赢了!' : 'AI赢了!') : '游戏中' }}
            </van-tag>
        </div>
        <div class="board-container">
            <div class="board" ref="boardRef">
                <div v-for="(row, rowIndex) in board" :key="rowIndex" class="row">
                    <div v-for="(cell, colIndex) in row" :key="colIndex" class="cell"
                        @click="handleCellClick(rowIndex, colIndex)">
                        <div class="piece" :class="{
                            'black-piece': cell === 1,
                            'white-piece': cell === 2,
                            'last-move': lastMove && lastMove.row === rowIndex && lastMove.col === colIndex
                        }"></div>
                    </div>
                </div>
            </div>
        </div>

        <div class="action-buttons">
            <van-button type="primary" @click="startNewGame" round>新游戏</van-button>
            <van-button type="info" @click="toggleDifficulty" round>
                难度: {{ difficulty === 'easy' ? '简单' : '困难' }}
            </van-button>
        </div>
    </div>
</template>

<script setup>
import { ref, computed, onMounted, nextTick, watch } from 'vue'
import { showToast } from 'vant'
import useSettingStore from '@/store/modules/setting'
const settings = useSettingStore()

// 在脚本开头添加Zobrist哈希初始化
const zobristTable = Array(BOARD_SIZE).fill().map(() =>
    Array(BOARD_SIZE).fill().map(() => ({
        [HUMAN]: Math.floor(Math.random() * 4294967296),
        [AI]: Math.floor(Math.random() * 4294967296)
    }))
)

let zobristHashValue = 0

const zobristHash = (board) => {
    let hash = 0
    for (let i = 0; i < BOARD_SIZE; i++) {
        for (let j = 0; j < BOARD_SIZE; j++) {
            if (board[i][j] !== EMPTY) {
                hash ^= zobristTable[i][j][board[i][j]]
            }
        }
    }
    return hash
}

// 游戏常量
const BOARD_SIZE = 15
const EMPTY = 0
const HUMAN = 1
const AI = 2

// 游戏状态
const board = ref(Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(EMPTY)))
const currentPlayer = ref('human') // human or ai
const winner = ref(null)
const difficulty = ref('easy') // easy, hard
const lastMove = ref(null)
const boardRef = ref(null)

// 初始化游戏
const initGame = () => {
    board.value = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(EMPTY))
    currentPlayer.value = 'human'
    winner.value = null
    lastMove.value = null
}

// 开始新游戏
const startNewGame = () => {
    initGame()
}

// 切换难度
const toggleDifficulty = () => {
    const difficulties = ['easy', 'hard']
    const currentIndex = difficulties.indexOf(difficulty.value)
    difficulty.value = difficulties[(currentIndex + 1) % difficulties.length]
    showToast(`已切换为${difficulty.value === 'easy' ? '简单' : '困难'}难度`)
}

// 处理玩家点击
const handleCellClick = (row, col) => {
    if (winner.value || currentPlayer.value !== 'human' || board.value[row][col] !== EMPTY) {
        return
    }
    // 更新哈希值
    zobristHashValue ^= zobristTable[row][col][HUMAN]

    // 玩家落子
    board.value[row][col] = HUMAN
    lastMove.value = { row, col }

    // 检查玩家是否获胜
    if (checkWin(row, col, HUMAN)) {
        winner.value = 'human'
        showToast('恭喜你赢了!')
        return
    }

    // 切换到AI回合
    currentPlayer.value = 'ai'

    // AI思考并落子
    setTimeout(() => {
        aiMove()
    }, 500)
}

// AI落子
const aiMove = () => {
    if (winner.value) return

    let move
    switch (difficulty.value) {
        case 'easy':
            move = findMediumMove()
            break
        case 'hard':
            move = findBestMove()
            break
        default:
            move = findMediumMove()
    }

    if (move) {
        // 更新哈希值
        zobristHashValue ^= zobristTable[move.row][move.col][AI]

        board.value[move.row][move.col] = AI
        lastMove.value = { row: move.row, col: move.col }
        // 检查AI是否获胜
        if (checkWin(move.row, move.col, AI)) {
            winner.value = 'ai'
            showToast('你输了!')
            setTimeout(() => {
                startNewGame()
            }, 1500)
            return
        }
    }

    // 切换回玩家回合
    currentPlayer.value = 'human'
}

// 随机移动 (简单难度)
const findRandomMove = () => {
    const emptyCells = []
    for (let i = 0; i < BOARD_SIZE; i++) {
        for (let j = 0; j < BOARD_SIZE; j++) {
            if (board.value[i][j] === EMPTY) {
                emptyCells.push({ row: i, col: j })
            }
        }
    }

    if (emptyCells.length > 0) {
        return emptyCells[Math.floor(Math.random() * emptyCells.length)]
    }
    return null
}

// 简单难度AI (考虑简单进攻和防守)
const findMediumMove = () => {
    // 1. 检查AI是否有四连可以赢
    for (let i = 0; i < BOARD_SIZE; i++) {
        for (let j = 0; j < BOARD_SIZE; j++) {
            if (board.value[i][j] === EMPTY) {
                board.value[i][j] = AI
                if (checkWin(i, j, AI)) {
                    board.value[i][j] = EMPTY
                    return { row: i, col: j }
                }
                board.value[i][j] = EMPTY
            }
        }
    }

    // 2. 检查玩家是否有四连需要防守
    for (let i = 0; i < BOARD_SIZE; i++) {
        for (let j = 0; j < BOARD_SIZE; j++) {
            if (board.value[i][j] === EMPTY) {
                board.value[i][j] = HUMAN
                if (checkWin(i, j, HUMAN)) {
                    board.value[i][j] = EMPTY
                    return { row: i, col: j }
                }
                board.value[i][j] = EMPTY
            }
        }
    }

    // 3. 尝试在中心区域落子
    const center = Math.floor(BOARD_SIZE / 2)
    if (board.value[center][center] === EMPTY) {
        return { row: center, col: center }
    }

    // 4. 随机落子
    return findRandomMove()
}

// 评估函数 - 给棋盘位置打分
const evaluateBoard = () => {
    let score = 0
    // 检查所有可能的五子连线
    for (let i = 0; i < BOARD_SIZE; i++) {
        for (let j = 0; j < BOARD_SIZE; j++) {
            if (board.value[i][j] === AI) {
                // 对AI的棋子加分
                score += evaluatePoint(i, j, AI)
            } else if (board.value[i][j] === HUMAN) {
                // 对玩家的棋子减分
                score -= evaluatePoint(i, j, HUMAN)
            }
        }
    }
    return score
}

// 评估一个点的影响力
const evaluatePoint = (row, col, player) => {
    let score = 0
    const directions = [
        [0, 1],   // 水平
        [1, 0],   // 垂直
        [1, 1],   // 对角线
        [1, -1]   // 反对角线
    ]

    directions.forEach(([dx, dy]) => {
        let count = 1 // 当前连续棋子数
        let openEnds = 0 // 开放端数量
        let block = 0 // 被阻挡的数量

        // 正向检查
        let x = row + dx
        let y = col + dy
        let blocked = false
        while (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && !blocked) {
            if (board.value[x][y] === player) {
                count++
                x += dx
                y += dy
            } else if (board.value[x][y] === EMPTY) {
                openEnds++
                blocked = true
            } else {
                block++
                blocked = true
            }
        }
        if (!blocked) openEnds++

        // 反向检查
        x = row - dx
        y = col - dy
        blocked = false
        while (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && !blocked) {
            if (board.value[x][y] === player) {
                count++
                x -= dx
                y -= dy
            } else if (board.value[x][y] === EMPTY) {
                openEnds++
                blocked = true
            } else {
                block++
                blocked = true
            }
        }
        if (!blocked) openEnds++


        // 根据连续棋子和开放端评分
        if (count >= 5) {
            score += 100000 // 五连
        } else if (count === 4) {
            if (openEnds === 2) score += 10000 // 活四
            else if (openEnds === 1) score += 1000 // 冲四
        } else if (count === 3) {
            if (openEnds === 2) score += 500 // 活三
            else if (openEnds === 1) score += 100 // 冲三
        } else if (count === 2) {
            if (openEnds === 2) score += 50 // 活二
            else if (openEnds === 1) score += 10 // 冲二
        } else if (count === 1 && openEnds === 2) {
            score += 1 // 活一
        }
    })

    return score
}

// 快速评估函数 - 只评估最后一步周围区域
const evaluateBoardFast = () => {
    let score = 0
    // 只评估最后一步周围区域
    if (lastMove.value) {
        const { row, col } = lastMove.value
        for (let i = Math.max(0, row - 4); i <= Math.min(BOARD_SIZE - 1, row + 4); i++) {
            for (let j = Math.max(0, col - 4); j <= Math.min(BOARD_SIZE - 1, col + 4); j++) {
                if (board.value[i][j] === AI) {
                    score += evaluatePointFast(i, j, AI)
                } else if (board.value[i][j] === HUMAN) {
                    score -= evaluatePointFast(i, j, HUMAN)
                }
            }
        }
    }
    return score
}

const evaluatePointFast = (row, col, player) => {
    // 简化的评估函数，只检查4个方向
    let score = 0
    const dirs = [[0, 1], [1, 0], [1, 1], [1, -1]]

    dirs.forEach(([dx, dy]) => {
        let count = 1, open1 = 0, open2 = 0

        // 正向
        let x = row + dx, y = col + dy
        while (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE &&
            board.value[x][y] === player) {
            count++
            x += dx
            y += dy
        }
        if (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE &&
            board.value[x][y] === EMPTY) open1++
        // 反向
        x = row - dx
        y = col - dy
        while (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE &&
            board.value[x][y] === player) {
            count++
            x -= dx
            y -= dy
        }
        if (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE &&
            board.value[x][y] === EMPTY) open2++

        // 评分
        if (count >= 5) score += 100000
        else if (count === 4) {
            if (open1 + open2 >= 1) score += open1 + open2 === 2 ? 10000 : 1000
        }
        else if (count === 3) {
            if (open1 + open2 >= 1) score += open1 + open2 === 2 ? 500 : 100
        }
    })

    return score
}

// 极大极小算法搜索最佳移动
const findBestMove = () => {
    let bestScore = -Infinity
    let bestMove = null

    // 限制搜索深度以提高性能
    // 修改这里，从2增加到3或4
    const depth = 3 // 原先是2

    // 只搜索有棋子的周围位置以提高效率
    const candidates = getCandidateMoves()

    for (const move of candidates) {
        const { row, col } = move
        if (board.value[row][col] === EMPTY) {
            board.value[row][col] = AI
            const score = minimax(depth, -Infinity, Infinity, false)
            board.value[row][col] = EMPTY

            if (score > bestScore) {
                bestScore = score
                bestMove = move
            }
        }
    }

    return bestMove || findMediumMove()
}

// 获取候选移动位置 (周围有棋子的空位)
const getCandidateMoves = () => {
    const candidates = []
    const directions = [
        [-1, -1], [-1, 0], [-1, 1],
        [0, -1], [0, 1],
        [1, -1], [1, 0], [1, 1]
    ]

    for (let i = 0; i < BOARD_SIZE; i++) {
        for (let j = 0; j < BOARD_SIZE; j++) {
            if (board.value[i][j] !== EMPTY) {
                // 检查周围的空位
                for (const [dx, dy] of directions) {
                    const x = i + dx
                    const y = j + dy
                    if (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE &&
                        board.value[x][y] === EMPTY &&
                        !candidates.some(m => m.row === x && m.col === y)) {
                        candidates.push({ row: x, col: y })
                    }
                }
            }
        }
    }

    // 如果没有候选位置，返回中心或随机位置
    if (candidates.length === 0) {
        const center = Math.floor(BOARD_SIZE / 2)
        if (board.value[center][center] === EMPTY) {
            candidates.push({ row: center, col: center })
        } else {
            return getRandomMoves(5) // 返回5个随机位置
        }
    }

    return candidates
}

// 获取随机移动位置
const getRandomMoves = (count) => {
    const moves = []
    const emptyCells = []

    for (let i = 0; i < BOARD_SIZE; i++) {
        for (let j = 0; j < BOARD_SIZE; j++) {
            if (board.value[i][j] === EMPTY) {
                emptyCells.push({ row: i, col: j })
            }
        }
    }

    // 随机选择count个位置
    for (let i = 0; i < Math.min(count, emptyCells.length); i++) {
        const randomIndex = Math.floor(Math.random() * emptyCells.length)
        moves.push(emptyCells[randomIndex])
        emptyCells.splice(randomIndex, 1)
    }

    return moves
}

// 极大极小算法
const minimax = (depth, alpha, beta, isMaximizing) => {
    // 检查游戏是否结束
    const gameOver = checkGameOver()
    if (gameOver.aiWin) return 100000
    if (gameOver.humanWin) return -100000
    if (gameOver.draw) return 0

    // 达到搜索深度
    if (depth === 0) {
        // return evaluateBoard() // 使用完整评估函数，但这里我们用快速版本
        return evaluateBoardFast() // 使用快速评估函数
    }

    if (isMaximizing) {
        let maxScore = -Infinity
        const candidates = getCandidateMoves()

        for (const move of candidates) {
            const { row, col } = move
            if (board.value[row][col] === EMPTY) {
                board.value[row][col] = AI
                const score = minimax(depth - 1, alpha, beta, false)
                board.value[row][col] = EMPTY
                maxScore = Math.max(maxScore, score)
                alpha = Math.max(alpha, score)
                if (beta <= alpha) break // Alpha-Beta剪枝
            }
        }
        return maxScore
    } else {
        let minScore = Infinity
        const candidates = getCandidateMoves()

        for (const move of candidates) {
            const { row, col } = move
            if (board.value[row][col] === EMPTY) {
                board.value[row][col] = HUMAN
                const score = minimax(depth - 1, alpha, beta, true)
                board.value[row][col] = EMPTY
                minScore = Math.min(minScore, score)
                beta = Math.min(beta, score)
                if (beta <= alpha) break // Alpha-Beta剪枝
            }
        }
        return minScore
    }
}

// 检查游戏是否结束
const checkGameOver = () => {
    let aiWin = false
    let humanWin = false
    let draw = true

    // 检查棋盘上是否有五连
    outerLoop:
    for (let i = 0; i < BOARD_SIZE; i++) {
        for (let j = 0; j < BOARD_SIZE; j++) {
            if (board.value[i][j] === AI && checkWin(i, j, AI)) {
                aiWin = true
                break outerLoop
            }
            if (board.value[i][j] === HUMAN && checkWin(i, j, HUMAN)) {
                humanWin = true
                break outerLoop
            }
            if (board.value[i][j] === EMPTY) {
                draw = false
            }
        }
    }

    return { aiWin, humanWin, draw }
}

// 检查是否获胜
const checkWin = (row, col, player) => {
    const directions = [
        [0, 1],   // 水平
        [1, 0],   // 垂直
        [1, 1],   // 对角线
        [1, -1]   // 反对角线
    ]

    for (const [dx, dy] of directions) {
        let count = 1

        // 正向检查
        let x = row + dx
        let y = col + dy
        while (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && board.value[x][y] === player) {
            count++
            x += dx
            y += dy
        }

        // 反向检查
        x = row - dx
        y = col - dy
        while (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE && board.value[x][y] === player) {
            count++
            x -= dx
            y -= dy
        }

        if (count >= 5) {
            return true
        }
    }

    return false
}

watch(() => currentPlayer.value, () => {
    if (currentPlayer.value == 'ai') {
        settings.handlerLoadingShow(true)
    } else {
        settings.handlerLoadingShow(false)
    }
})

// 初始化游戏
onMounted(() => {
    initGame()
})
</script>

<style scoped>
.gomoku-container {
    max-width: 100%;
    margin: 0 auto;
    padding: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.game-info {
    margin: 10px 0;
    display: flex;
    gap: 10px;
    justify-content: center;
}

.board-container {
    width: 100%;
    max-width: 500px;
    margin: 0 auto;
    overflow: auto;
    display: flex;
    justify-content: center;
    align-items: center;
}

.board {
    display: inline-block;
    border: 2px solid #333;
    background-color: #dcb35c;
    margin: 20px 0;
}

.row {
    display: flex;
}

.cell {
    width: 40px;
    height: 40px;
    border: 1px solid #999;
    box-sizing: border-box;
    position: relative;
    cursor: pointer;
}

.piece {
    position: absolute;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    top: 2px;
    left: 2px;
    box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
}

.black-piece {
    background-color: #000;
}

.white-piece {
    background-color: #fff;
}

.last-move::after {
    content: '';
    position: absolute;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background-color: red;
    top: 8px;
    left: 8px;
}

.action-buttons {
    margin-top: 20px;
    display: flex;
    gap: 10px;
}

@media (max-width: 500px) {
    .cell {
        width: 20px;
        height: 20px;
    }

    .piece {
        width: 16px;
        height: 16px;
    }

    .last-move::after {
        width: 6px;
        height: 6px;
        top: 5px;
        left: 5px;
    }
}
</style>